package org.example.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.catalina.User;
import org.example.entity.Permissions;
import org.example.entity.Users;
import org.example.models.LoginUser;
import org.example.models.R;
import org.example.service.PermissionsService;
import org.example.service.UsersService;
import org.example.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
//OncePerRequestFilter:spring提供的过滤器，保证在一次请求中只执行一次，如果按照servlet api的话，那么我们的过滤器就得实现Filter接口
@Component
public class TokenFilter extends OncePerRequestFilter {

    List<String> ignoreURL = Arrays.asList("/login2","/index");

    ObjectMapper objectMapper= new ObjectMapper();

    AntPathMatcher antPathMatcher=new AntPathMatcher();

    @Autowired
    UsersService usersService;

    @Autowired
    PermissionsService permissionsService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String uri= request.getRequestURI();//获取请求路径
        boolean flag = ignoreURL.stream().anyMatch(item -> antPathMatcher.match(item, uri));
        if(flag){
            filterChain.doFilter(request, response);
            return;
        }
        String token =request.getHeader("token");
        if(token==null){
            response.setCharacterEncoding("utf-8");
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            R r=R.error(401,"请先登录");
            String json = objectMapper.writeValueAsString(r);
            response.getWriter().print(json);
            return;
        }

        boolean isExpired= JwtUtils.isExpired(token);
        if(isExpired){
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("UTF-8");
            R r = R.error(401,"令牌已经过期，请重新登陆");
            String json = objectMapper.writeValueAsString(r);
            response.getWriter().print(json);
            return;
        }
        //如果上面校验toekn成功
        //那么下面手动创建security的认证对象
        Integer userId = JwtUtils.getId(token);
        Users users=usersService.getById(userId);
        List<Permissions> permissions = permissionsService.getPermissions(userId);
        LoginUser loginUser=new LoginUser(users,permissions);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=
                new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
        //给Security设置认证对象
        SecurityContextHolder.getContext().setAuthentication((usernamePasswordAuthenticationToken));
        //将用户ID绑定到request对象中，方便后续使用
        request.setAttribute("userId",userId);
        //继续进行security的处理
        filterChain.doFilter(request, response);
    }
}
